//
//  SCCamera.m
//  OCRDemo
//
//  Created by 党帅 on 2019/6/4.
//  Copyright © 2019 党帅. All rights reserved.
//

#import "SCVinCamera.h"

@interface SCVinCamera ()<AVCaptureVideoDataOutputSampleBufferDelegate>
//@property (nonatomic, strong) AVCaptureDevice *device;
@property (nonatomic, strong) AVCaptureSession *session;
@property (nonatomic, strong) AVCaptureVideoDataOutput *videoOutput;
@property (nonatomic, strong) AVCaptureVideoPreviewLayer *preViewLayer;

@property (nonatomic, strong) CIFilter *cropFilter;
@property (nonatomic, strong) CIContext *cropContext;
//@property (nonatomic, assign) BOOL focusDone;   //手动取图不需要监听聚焦状态
@property(nonatomic, weak) UIView *previewLayerView;
@end

@implementation SCVinCamera

+ (instancetype)sharedInstance {
    
    static dispatch_once_t onceToken;
    static SCVinCamera *camera;
    dispatch_once(&onceToken, ^{
        camera = [[SCVinCamera alloc] init];
    });
    return camera;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        [self obtainAuth];
    }
    return self;
}

- (void)configureDevice {
    
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    if ([device lockForConfiguration:nil]) {
        
        if ([device isSmoothAutoFocusSupported]){
            device.smoothAutoFocusEnabled = YES;
        }
        
        if ([device isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]){
            device.focusMode = AVCaptureFocusModeContinuousAutoFocus;
        }
        [device unlockForConfiguration];
    }
    
    AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
    AVCaptureSession *session = [[AVCaptureSession alloc] init];
    if ([session canAddInput:deviceInput]) {
        [session addInput:deviceInput];
        _session = session;
    }
    
    _videoOutput = [AVCaptureVideoDataOutput new];
    if ([_session canAddOutput:_videoOutput]) {
        [_session addOutput:_videoOutput];
    }
    
    dispatch_queue_t queue = dispatch_queue_create("com.shuaiche.videOP", DISPATCH_QUEUE_SERIAL);
    [_videoOutput setSampleBufferDelegate:self queue:queue];
    [_videoOutput setVideoSettings:@{(id)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_420YpCbCr8BiPlanarFullRange)}];
    _session.sessionPreset = AVCaptureSessionPreset1280x720;
    [_session commitConfiguration];
    
    // 手动取图不需要监听聚焦状态
//    [device addObserver:self forKeyPath:@"adjustingFocus" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
    
}

- (void)setCropSize:(CGSize)cropSize {
    _cropSize = cropSize;
    
    CGFloat h = 0, w = 0;
    CGFloat y = 0;
    if (_session.sessionPreset == AVCaptureSessionPreset1280x720) {
        h = _cropSize.height * 1280;
        w = _cropSize.width * 1280;
        y = floorf(0.26 *1280);
    }
    _cropFilter = [CIFilter filterWithName:@"CICrop"];
    [_cropFilter setValue:[CIVector vectorWithX:y Y:15 Z:h W:w] forKey:@"inputRectangle"];
}

- (void)captureOutput:(AVCaptureOutput *)output didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {

    if (![_session isRunning]) {
        return;
    }
    
    if (![_delegate shouldGenerateImage]) {
        return;
    }

    if (output == _videoOutput) {
        if (_delegate) {
            CVImageBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
            
            CIImage *ciImage = [CIImage imageWithCVPixelBuffer:pixelBuffer options:nil];
            [_cropFilter setValue:ciImage forKey:@"inputImage"];
            ciImage = [_cropFilter outputImage];
            CGImageRef myImage = [self.cropContext createCGImage:ciImage fromRect:ciImage.extent];
            UIImage *image = [UIImage imageWithCGImage:myImage scale:1 orientation:UIImageOrientationRight];
            CGImageRelease(myImage);
            if ([NSThread isMainThread]) {
                [_delegate processImage:image];
            } else {
                dispatch_sync(dispatch_get_main_queue(), ^{
                    [_delegate processImage:image];
                });
            }
        }
    }
}

- (void)start {
    if (![_session isRunning]) {
        [_session startRunning];
    }
}

- (void)stop {
    if ([_session isRunning]) {
        [_session stopRunning];
    }
}

- (void)torchSwitch {
    
    NSArray *inputs = _session.inputs;
    AVCaptureDevice *dev = nil;
    for (AVCaptureInput *put in inputs) {
        if ([put isKindOfClass:AVCaptureDeviceInput.class]) {
            AVCaptureDeviceInput *device = (AVCaptureDeviceInput *)put;
            dev = device.device;
            break;
        }
    }
    
    AVCaptureTorchMode mode = [dev torchMode];
    if ([dev lockForConfiguration:nil]) {
        if (mode == AVCaptureTorchModeOn) {
            [dev setTorchMode:AVCaptureTorchModeOff];
        } else if (mode == AVCaptureTorchModeOff) {
            [dev setTorchMode:AVCaptureTorchModeOn];
        }
        [dev unlockForConfiguration];
    }
}

- (void)showInView:(UIView *)view {
    
    [_preViewLayer removeFromSuperlayer];
    self.preViewLayer.frame = view.bounds;
    [view.layer addSublayer:_preViewLayer];
}

- (void)showInView:(UIView *)view belowLayer:(CALayer *)layer {
    _previewLayerView = view;
    [_preViewLayer removeFromSuperlayer];
    self.preViewLayer.frame = view.bounds;
    [view.layer insertSublayer:_preViewLayer below:layer];
}

- (void)obtainAuth {
    AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
    if (status == AVAuthorizationStatusAuthorized) {
        [self configureDevice];
    } else if (status == AVAuthorizationStatusNotDetermined) {
        [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
            if (granted) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    [self configureDevice];
                    [self start];
                    [self showInView:_previewLayerView belowLayer:_previewLayerView.layer.sublayers.lastObject];
                });
            }
        }];
    } else {
        NSLog(@">>>无权限");
    }
}

//- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
//    BOOL adjustingFocus = [[change objectForKey:NSKeyValueChangeNewKey] isEqualToNumber:@1];
//    _focusDone = !adjustingFocus;
//    if (_focusDone) {
//        [_device removeObserver:self forKeyPath:@"adjustingFocus"];
//        if ([_device lockForConfiguration:nil]) {
//            if ([_device isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]){
//                _device.focusMode = AVCaptureFocusModeContinuousAutoFocus;
//            }
//            [_device unlockForConfiguration];
//        }
//    }
//}

- (AVCaptureVideoPreviewLayer *)preViewLayer {
    if (!_preViewLayer) {
        _preViewLayer = [AVCaptureVideoPreviewLayer layerWithSession:_session];
    }
    if (!_preViewLayer.session) {
        _preViewLayer = [AVCaptureVideoPreviewLayer layerWithSession:_session];
    }
    return _preViewLayer;
}


- (CIContext *)cropContext {
    if (!_cropContext) {
       _cropContext = [CIContext contextWithOptions:nil];
    }
    return _cropContext;
}

@end
